package net.wicp.tams.common.thread;

import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;

import net.wicp.tams.common.CallbackUpdate;
import net.wicp.tams.common.Conf;
import net.wicp.tams.common.thread.rejected.RejectedExecutionForLog;

/**
 * 
 * @author 偏锋书生
 *
 */
public class ThreadPool {
	private static final java.util.Map<String, ExecutorService> executorServiceMap = new java.util.HashMap<String, ExecutorService>();
	

	private static Properties newProperties = null;

	static {
		Conf.addCallBack(new CallbackUpdate() {
			@Override
			public void doReshConf(Properties oldProperties, Properties newProperties) {
				ThreadPool.newProperties = newProperties;
				shutdown();
			}
		}, "common.apiext.thread.pool.");
	}

	/*****
	 * 通过名字得到线程池
	 * 
	 * @param poolname
	 *            池名
	 * @param properties
	 *            要实例的池的属性
	 * @return 返回的执行器
	 */
	public static final ExecutorService getThreadPoolByName(String poolname, Properties properties) {
		if (StringUtils.isEmpty(poolname)) {
			throw new IllegalArgumentException("需要传入线程池名称");
		}
		synchronized (executorServiceMap) {
			if (executorServiceMap.containsKey(poolname)) {
				return executorServiceMap.get(poolname);
			} else {
				String preStr = "common.apiext.thread.pool." + poolname + ".";
				String coreSize = properties.getProperty(preStr + "coreSize");
				String maxSize = properties.getProperty(preStr + "maxSize");
				String queueSize = properties.getProperty(preStr + "queueSize");
				String keepAliveTime = properties.getProperty(preStr + "keepAliveTime");
				String unit = properties.getProperty(preStr + "unit");
				if (StringUtils.isEmpty(coreSize) || StringUtils.isEmpty(maxSize) || StringUtils.isEmpty(queueSize)) {
					throw new IllegalArgumentException("池核心数、最大数、队列数必须定义");
				}
				int coreSizeInt = Integer.parseInt(coreSize);
				int maxSizeInt = Integer.parseInt(maxSize);
				int queueSizeInt = Integer.parseInt(queueSize);
				int keepAliveTimeInt = StringUtils.isEmpty(keepAliveTime) ? 10 : Integer.parseInt(keepAliveTime);
				TimeUnit unitT = StringUtils.isEmpty(unit) ? TimeUnit.SECONDS : getTimeUnit(unit);
				BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(queueSizeInt);
				ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSizeInt, maxSizeInt, keepAliveTimeInt, unitT,
						queue, new RejectedExecutionForLog());				
				executor.allowCoreThreadTimeOut(true);
				executorServiceMap.put(poolname, executor);
				return executor;
			}
		}
	}
	
	/***
	 * 线程池关闭
	 */
	public static void shutdown() {
		for (String poolname : executorServiceMap.keySet()) {
			executorServiceMap.get(poolname).shutdown();
		}
		executorServiceMap.clear();
	}
	
	/***
	 * 得到所有线程池
	 * @return
	 */
	public static java.util.Map<String, ExecutorService> getExecutorservicemap() {
		return executorServiceMap;
	}

	/***
	 * 得到默认的线程池
	 * 
	 * #线程池说明，corePoolSize：池核心线程大小、maxSize：最大线程大小、queue：等待队列大小、keepAliveTime：
	 * 线程保存时间、unit：单位，默认为秒 #默认线程的配置<br>
	 * thread.pool.default.poolname=default thread.pool.default.coreSize=40
	 * thread.pool.default.maxSize=60 thread.pool.default.queueSize=100
	 * thread.pool.default.keepAliveTime=60 thread.pool.default.unit=SECONDS
	 * 
	 * @return 线程池
	 */
	public static final ExecutorService getDefaultPool() {
		if (ThreadPool.newProperties == null) {
			ThreadPool.newProperties = Conf.copyProperties();
		}
		return getThreadPoolByName("default", ThreadPool.newProperties);
	}

	private static TimeUnit getTimeUnit(String TimeUnitStr) {
		if (StringUtils.isEmpty(TimeUnitStr)) {
			return null;
		}
		for (TimeUnit timeUnit : TimeUnit.values()) {
			if (timeUnit.name().equals(TimeUnitStr)) {
				return timeUnit;
			}
		}
		return null;
	}

}
